/*
 * Copyright© 2003-2019 浙江汇信科技有限公司, All Rights Reserved.
 */
package com.icinfo.cloud.provider.punish.common.datareport.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.enums.RecordSaveTypeEnum;
import com.icinfo.cloud.provider.common.enums.YesOrNoEnum;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.common.utils.BaseUtil;
import com.icinfo.cloud.provider.punish.common.datareport.dto.CaseDataReportStageInfoQueryDto;
import com.icinfo.cloud.provider.punish.common.datareport.dto.CaseDataReportStageInfoSaveDto;
import com.icinfo.cloud.provider.punish.common.datareport.enums.ReportDataTypeEnum;
import com.icinfo.cloud.provider.punish.common.datareport.mapper.CaseDataReportStageInfoMapper;
import com.icinfo.cloud.provider.punish.common.datareport.model.CaseDataReportStageInfo;
import com.icinfo.cloud.provider.punish.common.datareport.service.ICaseDataReportStageInfoService;
import com.icinfo.cloud.provider.punish.common.datareport.vo.CaseDataReportStageInfoVo;
import com.icinfo.cloud.provider.punish.ucase.casemain.dto.CaseMainDetailAuxiliaryInfoRequest;
import com.icinfo.cloud.provider.punish.ucase.casemain.enums.CaseTypeEnum;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseMainDetailSimpleInfoMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainDetailAuxiliaryInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainDetailSimpleInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseMainDetailAuxiliaryInfoService;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseMainInfoService;
import com.icinfo.cloud.provider.punish.ucase.casemain.vo.CaseMainInfoVo;
import com.icinfo.framework.core.service.support.MyBatisServiceSupport;
import com.icinfo.framework.mybatis.mapper.entity.Example;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 描述: 案件数据上报阶段信息 case_data_report_stage_info 对应的Service接口实现类.<br>
 *
 * @author framework generator
 * @date 2022年04月19日
 */
@Service
@Slf4j
public class CaseDataReportStageInfoServiceImpl extends MyBatisServiceSupport implements ICaseDataReportStageInfoService {
    @Resource
    private CaseDataReportStageInfoMapper caseDataReportStageInfoMapper;
    @Resource
    private ICaseDataReportStageInfoService caseDataReportStageInfoService;
    @Resource
    private ICaseMainInfoService caseMainInfoService;
    @Resource
    private CaseMainDetailSimpleInfoMapper caseMainDetailSimpleInfoMapper;
    @Resource
    private ICaseMainDetailAuxiliaryInfoService caseMainDetailAuxiliaryInfoService;

    /**
     * 描述：保存案件数据上报阶段信息
     *
     * @param saveDto {@link CaseDataReportStageInfoSaveDto}
     * @return String 保存时出现的错误信息
     * @author xiangyuyu
     * @date 2022-04-19 13:41
     */
    @Override
    public String saveCaseDataReportStageInfo(CaseDataReportStageInfoSaveDto saveDto) {
        log.info("saveCaseDataReportStageInfo start... saveDto:{}", saveDto);
        if (ObjectUtils.isEmpty(saveDto)) {
            return "未指定数据上报阶段信息";
        }
        String operateType = saveDto.getOperateType();
        if (ObjectUtils.isEmpty(operateType) || !RecordSaveTypeEnum.isLegalEnumCode(operateType)) {
            return "未指定有效的操作类型（1-新增/2-修改/3-暂存）";
        }
        if (ObjectUtils.isEmpty(saveDto.getCaseId())) {
            return "未指定案件id";
        }

        String reportStageTag = saveDto.getReportStageTag();
        if (!ReportDataTypeEnum.isLegalEnumCode(reportStageTag)) {
            return "未指定有效的上报阶段标识 ReportDataTypeEnum";
        }

        if (RecordSaveTypeEnum.MOD.getCode().equals(operateType)) {
            if (ObjectUtils.isEmpty(saveDto.getId())) {
                return "修改记录时清指定主键id";
            } else {
                //修改
                CaseDataReportStageInfo caseDataReportStageInfo = new CaseDataReportStageInfo();
                BeanUtils.copyProperties(saveDto, caseDataReportStageInfo);
                caseDataReportStageInfo.setReportStageSort(ReportDataTypeEnum.getSortByCode(reportStageTag));
                caseDataReportStageInfoMapper.updateByPrimaryKeySelective(caseDataReportStageInfo);
            }

        } else {
            //非修改
            CaseDataReportStageInfo caseDataReportStageInfo = new CaseDataReportStageInfo();
            BeanUtils.copyProperties(saveDto, caseDataReportStageInfo);
            caseDataReportStageInfo.setId(BaseUtil.createUid());
            caseDataReportStageInfo.setReportStageSort(ReportDataTypeEnum.getSortByCode(reportStageTag));
            if(ObjectUtils.isEmpty(caseDataReportStageInfo.getPartyId())){
                caseDataReportStageInfo.setPartyId(Constant.STRING_HORIZONTAL_BARS);
            }
            try {
                caseDataReportStageInfoMapper.insertSelective(caseDataReportStageInfo);
            } catch (Exception e){
                e.printStackTrace();
                if (e.getMessage().contains(Constant.STRING_DUPLICATE_ENTRY) ||
                        e.getMessage().contains(Constant.STRING_DUPLICATE_ENTRY_LOWER)) {
                    log.error("重复添加");
                } else {
                    log.error(e.getMessage());
                }
            }
        }
        log.info("saveCaseDataReportStageInfo end...");
        return null;
    }

    /**
     * 描述：获取案件数据上报阶段信息
     *
     * @param queryDto {@link CaseDataReportStageInfoQueryDto}
     * @return {@link List < CaseDataReportStageInfoVo >} 案件数据上报阶段信息
     * @author xiangyuyu
     * @date 2022-04-19 13:41
     */
    @Override
    public List<CaseDataReportStageInfoVo> getCaseDataReportStageInfoList(CaseDataReportStageInfoQueryDto queryDto) {
        String caseId = queryDto.getCaseId();
        if (ObjectUtils.isEmpty(caseId)) {
            throw new BusinessException("未指定案件id");
        }
        List<CaseDataReportStageInfoVo> list = caseDataReportStageInfoMapper.selectCaseDataReportStageInfoList(queryDto);
        return list;
    }

    /**
     * 描述：初始化案件上报阶段信息
     *
     * @param caseId  案件id
     * @param partyId 当事人id
     * @author xiangyuyu
     * @date 2022-04-19 16:08
     */
    @Override
    public void initCaseReportStageInfo(String caseId, String partyId) {
        CaseDataReportStageInfoQueryDto queryDto = new CaseDataReportStageInfoQueryDto();
        queryDto.setCaseId(caseId);
        queryDto.setPartyId(partyId);
        List<CaseDataReportStageInfoVo> list = getCaseDataReportStageInfoList(queryDto);
        if (ObjectUtils.isEmpty(list) || list.size() == 0) {
            //初始化新增
            CaseDataReportStageInfoSaveDto saveDto;
            for (ReportDataTypeEnum value : ReportDataTypeEnum.values()) {
                saveDto = new CaseDataReportStageInfoSaveDto();
                saveDto.setId(BaseUtil.createUid());
                saveDto.setOperateType(RecordSaveTypeEnum.ADD.getCode());
                saveDto.setReportStageTag(value.getCode());
                saveDto.setReportStageSort(value.getSort());
                saveDto.setIsFinishReport(YesOrNoEnum.NO.getCode());
                saveDto.setFailCount(Constant.INTEGER_0);
                saveDto.setCaseId(caseId);
                saveDto.setPartyId(partyId);
                caseDataReportStageInfoService.saveCaseDataReportStageInfo(saveDto);
            }
        }
    }

    /**
     * 描述：校验案件指定阶段数据是否已经上报完成
     *
     * @param reportStageTag 上报阶段标识
     * @param caseId         案件id
     * @param partyId        当事人id
     * @return true-是/false-否
     * @author xiangyuyu
     * @date 2022-04-19 19:22
     */
    @Override
    public boolean checkStageInfoIsReportSuccess(String reportStageTag, String caseId, String partyId) {
        boolean flag = true;
        //查看案件上报阶段信息表中该案件、阶段的数据是否已经上报成功
        CaseDataReportStageInfoQueryDto queryDto = new CaseDataReportStageInfoQueryDto();
        queryDto.setCaseId(caseId);
        queryDto.setReportStageTag(reportStageTag);
        queryDto.setIsFinishReport(YesOrNoEnum.YES.getCode());
        queryDto.setPartyId(partyId);
        List<CaseDataReportStageInfoVo> list = caseDataReportStageInfoService.getCaseDataReportStageInfoList(queryDto);
        if (ObjectUtils.isEmpty(list) || list.size() == 0) {
            flag = false;
        }
        return flag;
    }

    /**
     * 描述：校验是否需要上报数据
     *
     * @param reportStageTag 上报阶段标识
     * @param caseId         案件id
     * @param partyId        当事人id
     * @return true-是/false-否
     * @author xiangyuyu
     * @date 2022-04-19 19:22
     */
    @Override
    public boolean checkIsShouldReport(String reportStageTag, String caseId, String partyId) {
        boolean flag = false;
        //简易处罚，轻微违法,且不处罚，不上报
        Example example = new Example(CaseMainDetailSimpleInfo.class);
        example.createCriteria().andEqualTo("caseId", caseId);
        List<CaseMainDetailSimpleInfo> simpleInfoList = caseMainDetailSimpleInfoMapper.selectByExample(example);
        if(ObjectUtil.isNotEmpty(simpleInfoList)){
            CaseMainDetailSimpleInfo info = simpleInfoList.get(Constant.INTEGER_0);
            if(Constant.STRING_1.equals(info.getIsSlightIllegal()) && Constant.STRING_2.equals(info.getInvestConclusion())){
                log.info("简易处罚，轻微违法,且不处罚，不上报-caseId:{}", caseId);
                return false;
            }
        }
        /*
        20221129 新增限制（上个阶段数据上报失败，该阶段不进行数据上报）
        BASE,INVESTIGATE,INFORM/HEAR,DECISION,EXECUTE,CASE_CLOSED
         */
        if (!ReportDataTypeEnum.isLegalEnumCode(reportStageTag)) {
            log.error("非法上报数据类型枚举");
            return flag;
        }
        ReportDataTypeEnum reportDataTypeEnum = ReportDataTypeEnum.getEnumInfo(reportStageTag);
        if (ObjectUtils.isEmpty(reportDataTypeEnum)) {
            return flag;
        }
        CaseDataReportStageInfoQueryDto queryDto = new CaseDataReportStageInfoQueryDto();
        //上个阶段的数据上报标签
        boolean latestStageReportSuccess = false;
        //数据上报标签列表
        List<String> reportStageTags = new ArrayList<>();
        //获取上个阶段上报情况
        queryDto.setCaseId(caseId);
        queryDto.setIsFinishReport(YesOrNoEnum.YES.getCode());
        queryDto.setPartyId(partyId);
        if (ReportDataTypeEnum.BASE.getCode().equals(reportStageTag)) {
            reportStageTags.add(reportStageTag);
            latestStageReportSuccess = true;
        } else {
            //决定阶段，简易处罚需要特殊处理（简易处罚对应处罚告知信息没有上报，直接报决定信息）
            if (ReportDataTypeEnum.DECISION.getCode().equals(reportStageTag)) {
                CaseMainInfoVo caseMainInfo = caseMainInfoService.getCaseMainInfo(caseId);
                String caseType = caseMainInfo.getCaseType();
                if (CaseTypeEnum.SIMPLE_PROCEDURE.getCode().equals(caseType)) {
                    reportStageTags.add(ReportDataTypeEnum.BASE.getCode());
                } else {
                    reportStageTags.add(ReportDataTypeEnum.INFORM.getCode());
                    reportStageTags.add(ReportDataTypeEnum.HEAR.getCode());
                }
            } else if (ReportDataTypeEnum.HEAR.getCode().equals(reportStageTag)) {
                reportStageTags.add(ReportDataTypeEnum.INVESTIGATE.getCode());
            } else {
                //根据当前阶段上报标签推断出上个阶段上报标签
                List<String> reportTagList = new ArrayList<>();
                for (ReportDataTypeEnum ele : ReportDataTypeEnum.values()) {
                    if(ReportDataTypeEnum.OBTAIN.getCode().equals(ele.getCode())){
                        continue;
                    }
                    reportTagList.add(ele.getCode());
                }
                //当前下标
                int currentFlagIndex = 0;
                for (int i = 0; i < reportTagList.size(); i++) {
                    if (reportTagList.get(i).equals(reportStageTag)) {
                        currentFlagIndex = i;
                        break;
                    }
                }
                //currentFlagIndex 不可能为0
                reportStageTags.add(reportTagList.get(--currentFlagIndex));
                if(ReportDataTypeEnum.CASE_CLOSED.getCode().equals(reportStageTag)){
                    CaseMainDetailAuxiliaryInfoRequest request = new CaseMainDetailAuxiliaryInfoRequest(caseId,partyId);
                    List<CaseMainDetailAuxiliaryInfo> caseMainDetailAuxiliaryList = caseMainDetailAuxiliaryInfoService.getCaseMainDetailAuxiliaryInfo(request);
                    if(!ObjectUtils.isEmpty(caseMainDetailAuxiliaryList) && caseMainDetailAuxiliaryList.size() > 0){
                        CaseMainDetailAuxiliaryInfo caseMainDetailAuxiliaryInfo = caseMainDetailAuxiliaryList.get(Constant.INTEGER_0);
                        if(Constant.STRING_2.equals(caseMainDetailAuxiliaryInfo.getInvestConclusion())){
                            reportStageTags.add(ReportDataTypeEnum.DECISION.getCode());
                        }
                    }
                }
            }
            queryDto.setReportStageTagList(reportStageTags);
            List<CaseDataReportStageInfoVo> list = caseDataReportStageInfoService.getCaseDataReportStageInfoList(queryDto);
            if (!ObjectUtils.isEmpty(list) && list.size() > 0) {
                latestStageReportSuccess = true;
            }
        }
        if (!latestStageReportSuccess) {
            return flag;
        }
        //查看案件上报阶段信息表中该案件、阶段的数据是否已经上报成功
        queryDto.setReportStageTagList(null);
        queryDto.setReportStageTag(reportStageTag);
        List<CaseDataReportStageInfoVo> list = caseDataReportStageInfoService.getCaseDataReportStageInfoList(queryDto);
        if (ObjectUtils.isEmpty(list) || list.size() == 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 描述：上报动作结束后续操作
     *
     * @param caseId          案件id
     * @param isReportSuccess 是否上报成功
     * @param reportStageTag  上报阶段标识
     * @param failReason      失败原因
     * @param partyId         当事人id
     * @return
     * @author xiangyuyu
     * @date 2022-04-19 19:51
     */
    @Override
    public void dealAfterReport(String caseId, boolean isReportSuccess, String reportStageTag, String failReason, String partyId) {
        log.info("dealAfterReport start...caseId:{},isReportSuccess:{},reportStageTag:{},failReason:{},partyId:{}",
                caseId,isReportSuccess,reportStageTag,failReason,partyId);
        Example query = new Example(CaseDataReportStageInfo.class);
        Example.Criteria criteria = query.createCriteria();
        criteria.andEqualTo("caseId", caseId).andEqualTo("reportStageTag", reportStageTag);
        if (!ObjectUtils.isEmpty(partyId)) {
            criteria.andEqualTo("partyId", partyId);
        }
        String id = null;
        int failCount = 0;
        List<CaseDataReportStageInfo> list = caseDataReportStageInfoMapper.selectByExample(query);
        if (!ObjectUtils.isEmpty(list) && list.size() > 0) {
            //取第一条
            CaseDataReportStageInfo info = list.get(Constant.INTEGER_0);
            id = info.getId();
            failCount = info.getFailCount();
        }
        LocalDateTime now = LocalDateTime.now();
        CaseDataReportStageInfoSaveDto saveDto = new CaseDataReportStageInfoSaveDto();
        saveDto.setReportStageTag(reportStageTag);
        saveDto.setId(id);
        saveDto.setCaseId(caseId);
        saveDto.setReportFinishTime(now);
        saveDto.setLatestReportTime(now);
        saveDto.setLatestReportFailReason(failReason);
        saveDto.setPartyId(partyId);
        if (isReportSuccess) {
            //成功
            saveDto.setIsFinishReport(YesOrNoEnum.YES.getCode());
        } else {
            //失败
            saveDto.setIsFinishReport(YesOrNoEnum.NO.getCode());
            saveDto.setFailCount(failCount++);
        }
        if (!ObjectUtils.isEmpty(id)) {
            saveDto.setId(id);
            saveDto.setOperateType(RecordSaveTypeEnum.MOD.getCode());
        } else {
            saveDto.setOperateType(RecordSaveTypeEnum.ADD.getCode());
        }
        caseDataReportStageInfoService.saveCaseDataReportStageInfo(saveDto);
        log.info("dealAfterReport end");
    }
}